//! 时间处理工具

use chrono::{DateTime, Duration, Local, NaiveDateTime, Utc};

/// 获取当前时间戳（秒）
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::time_utils::current_timestamp;
/// 
/// let timestamp = current_timestamp();
/// assert!(timestamp > 0);
/// ```
pub fn current_timestamp() -> i64 {
    Utc::now().timestamp()
}

/// 获取当前时间戳（毫秒）
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::time_utils::current_timestamp_millis;
/// 
/// let timestamp = current_timestamp_millis();
/// assert!(timestamp > 0);
/// ```
pub fn current_timestamp_millis() -> i64 {
    Utc::now().timestamp_millis()
}

/// 格式化时间
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::time_utils::format_time;
/// use chrono::Utc;
/// 
/// let now = Utc::now();
/// let formatted = format_time(&now, "%Y-%m-%d %H:%M:%S");
/// assert!(formatted.len() > 0);
/// ```
pub fn format_time<Tz: chrono::TimeZone>(dt: &DateTime<Tz>, format: &str) -> String
where
    Tz::Offset: std::fmt::Display,
{
    dt.format(format).to_string()
}

/// 解析时间字符串
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::time_utils::parse_time;
/// 
/// let dt = parse_time("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S");
/// assert!(dt.is_ok());
/// ```
pub fn parse_time(time_str: &str, format: &str) -> Result<DateTime<Local>, chrono::ParseError> {
    let naive_dt = NaiveDateTime::parse_from_str(time_str, format)?;
    Ok(DateTime::<Local>::from_naive_utc_and_offset(
        naive_dt,
        *Local::now().offset(),
    ))
}

/// 计算两个时间之间的差值（天数）
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::time_utils::{days_between, parse_time};
/// 
/// let start = parse_time("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// let end = parse_time("2023-01-05 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// let days = days_between(&start, &end);
/// assert_eq!(days, 4);
/// ```
pub fn days_between<Tz: chrono::TimeZone>(start: &DateTime<Tz>, end: &DateTime<Tz>) -> i64
where
    Tz::Offset: std::fmt::Display,
{
    let duration = end.clone().signed_duration_since(start.clone());
    duration.num_days()
}

/// 在指定时间基础上增加天数
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::time_utils::{add_days, parse_time};
/// 
/// let start = parse_time("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// let result = add_days(&start, 5);
/// let expected = parse_time("2023-01-06 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// assert_eq!(result.timestamp(), expected.timestamp());
/// ```
pub fn add_days<Tz: chrono::TimeZone>(dt: &DateTime<Tz>, days: i64) -> DateTime<Tz>
where
    Tz::Offset: std::fmt::Display,
{
    dt.clone() + Duration::days(days)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_current_timestamp() {
        let timestamp = current_timestamp();
        assert!(timestamp > 0);
    }

    #[test]
    fn test_current_timestamp_millis() {
        let timestamp = current_timestamp_millis();
        assert!(timestamp > 0);
    }

    #[test]
    fn test_format_time() {
        let now = Utc::now();
        let formatted = format_time(&now, "%Y-%m-%d %H:%M:%S");
        assert!(formatted.len() > 0);
    }

    #[test]
    fn test_parse_time() {
        let dt = parse_time("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S");
        assert!(dt.is_ok());
    }

    #[test]
    fn test_days_between() {
        let start = parse_time("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
        let end = parse_time("2023-01-05 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
        let days = days_between(&start, &end);
        assert_eq!(days, 4);
    }

    #[test]
    fn test_add_days() {
        let start = parse_time("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
        let result = add_days(&start, 5);
        let expected = parse_time("2023-01-06 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
        assert_eq!(result.timestamp(), expected.timestamp());
    }
}